dnl Process this file with autoconf to produce a configure script.
dnl
dnl
dnl
dnl On AIX, we need xlc_r or cc_r if not explicitly set
define(S48_CC, [dnl
  case "$target" in
    *-*-aix*) dnl
	if test -z "$CC" ; then
	  AC_CHECK_PROGS(CC,cc_r xlc_r cc)
	fi
    ;;
esac
])
dnl
dnl
dnl Tests if it can compile and link with "-arch"-Flag on MacOSX,
dnl keeps the "-arch"-Flag in the CFLAGS and LDFLAGS if test is
dnl successfull.
define(S48_OSX_ARCH_CHECK, [dnl
AC_MSG_CHECKING([for gcc argument $1])
save_CFLAGS="$CFLAGS"
save_LDFLAGS="$LDFLAGS"
CFLAGS="$CFLAGS -arch $1"
LDFLAGS="$LDFLAGS -arch $1"
compiles=0
links=0
AC_TRY_COMPILE([],[],compiles=1, compiles=0)
AC_TRY_LINK([],[],links=1, links=0)
if test "$links" = "1" -a "$compiles" = "1"; then
  AC_MSG_RESULT([OK])
else
  CFLAGS="$save_CFLAGS"
  LDFLAGS="$save_LDFLAGS"
  AC_MSG_RESULT([failed])
fi
])
dnl
dnl
dnl Checks for valid "-arch"-Flags on MacOSX depending on the
dnl parameters build_universal (see S48_ENABLE_UNIVERSAL_BINARY)
dnl and force_32 (see S48_ENABLE_FORCE_32BIT).
define(S48_OSX_ARCH_FLAGS, [dnl
build_universal="$1"
force_32="$2"
if test "$build_universal" = 1 -a "$force_32" = 1; then 
  S48_OSX_ARCH_CHECK(i386,32)
  S48_OSX_ARCH_CHECK(ppc,32)
elif test "$build_universal" = 1 -a "$force_32" = 0; then
  if test "$BIT_SUFFIX" = 32; then
    S48_OSX_ARCH_CHECK(i386,32)
    S48_OSX_ARCH_CHECK(ppc,32)
  elif test "$BIT_SUFFIX" = 64; then
    S48_OSX_ARCH_CHECK(x86_64,64)
    S48_OSX_ARCH_CHECK(ppc64,64)
  fi
fi
])
dnl
dnl
dnl Force to use 32bit implementation.
define(S48_ENABLE_FORCE_32BIT, [dnl
AC_MSG_CHECKING([whether we must build a 32bit binary])
dnl
AC_ARG_ENABLE([force-32bit],
[AC_HELP_STRING([--enable-force-32bit],
		[Build a 32bit binary on architectures where this is not the default])],
	[dnl 
         S48_FORCE_32_P="1"
	 BIT_SUFFIX="32"
	 dnl For now only a Linux/AMD x86_64 version:
	 case "$host" in
		x86_64-*-linux-gnu )
	         CFLAGS="${CFLAGS} -m32";
		 LDFLAGS="${LDFLAGS} -m32";
		 dnl This is needed if 'gcc' resp. 'ld' is used to link a dynamic external below
		 GCC_LDFLAGS="${GCC_LDFLAGS} -m32";
		 LD_LDFLAGS="${LD_LDFLAGS} -melf_i386";
		;;
                *darwin* ) dnl AC_MSG_RESULT([Found Darwin, will check later.])
                ;;
		* ) AC_MSG_ERROR([Don't know how to build a 32bit binary on this architecture])
		;;
	 esac
	 AC_DEFINE([BUILD_32BIT], 1,
		   [Define if we are building a 32bit binary on architectures where this is not the default.])
	 AC_MSG_RESULT(yes)],
   	[dnl
         S48_FORCE_32_P="0"
	 AC_MSG_RESULT(no)])])
dnl
dnl
dnl Determines the number of bits per byte
define(S48_DETERMINE_BITS_PER_BYTE, [dnl
AC_MSG_CHECKING(bits per byte)
AC_CACHE_VAL(ac_cv_sizeof_void_p,
	[AC_TRY_RUN([#include <stdio.h>
		#include <stdlib.h>
		main()
		{
		  unsigned char c = 1;
		  int i = 0;
		  FILE *f=fopen("conftestval", "w");
		  if (!f) exit(1);
		  while (c != 0) {
		    i++;
		    c = c << 1;
		  }
		  fprintf(f, "%d\n", i);
		  exit(0);
		}],
	    ac_cv_bits_per_byte=`cat conftestval`,
	    ac_cv_bits_per_byte=0,
	    AC_MSG_ERROR(failed to compile test program))])
     if test "$ac_cv_bits_per_byte" = "0" -o "$ac_cv_bits_per_byte" = ""; then
       AC_MSG_ERROR([Unable to determine bits per byte, see config.log for details.]);
     fi
     AC_MSG_RESULT($ac_cv_bits_per_byte)
     AC_DEFINE_UNQUOTED(BITS_PER_BYTE, [$ac_cv_bits_per_byte], [Check for the number of bits per byte])
])
dnl
dnl
dnl Determines the size of a pointer.
define(S48_DETERMINE_POINTER_SIZE, [dnl
dnl Our own version of AC_CHECK_SIZEOF([void *])
AC_MSG_CHECKING(size of void *)
AC_CACHE_VAL(ac_cv_sizeof_void_p,
	[AC_TRY_RUN([#include <stdio.h>
		#include <stdlib.h>
		main()
		{
		  FILE *f=fopen("conftestval", "w");
		  if (!f) exit(1);
		  fprintf(f, "%d\n", (int)sizeof(void *));
		  exit(0);
		}],
	    ac_cv_sizeof_void_p=`cat conftestval`,
	    ac_cv_sizeof_void_p=0,
	    AC_MSG_ERROR(failed to compile test program))])
     if test "$ac_cv_sizeof_void_p" = "0" -o "$ac_cv_sizeof_void_p" = ""; then
       AC_MSG_ERROR([Unable to determine sizeof (void *), see config.log for details.]);
     fi
     AC_MSG_RESULT($ac_cv_sizeof_void_p)
     AC_DEFINE_UNQUOTED(SIZEOF_VOID_P, [$ac_cv_sizeof_void_p], [Check for sizeof (void *)])
])
dnl
dnl
dnl Determines the number of bits of desired build.
define(S48_DETERMINE_BIT_SUFFIX, [dnl
     AC_MSG_CHECKING([for BIT_SUFFIX])
     if test $BIT_SUFFIX; then
       AC_MSG_RESULT([You forced BIT_SUFFIX to be $BIT_SUFFIX.])
     else
       BIT_SUFFIX=`expr $ac_cv_sizeof_void_p \* $ac_cv_bits_per_byte`
       AC_MSG_RESULT($BIT_SUFFIX)
     fi
     AC_DEFINE_UNQUOTED(WORDSIZE, [$BIT_SUFFIX], [Check for number of bits in a word])
])
dnl
dnl
dnl
dnl Option to build an universal binary on MacOSX.
define(S48_ENABLE_UNIVERSAL_BINARY, [dnl
AC_MSG_CHECKING([whether we are building a Universal Binary])
dnl
AC_ARG_ENABLE([universal-binary],
[AC_HELP_STRING([--enable-universal-binary],
		[Build MacOS X Universal Binary])],
	[dnl
	 case $host in
           *darwin* ) S48_BUILD_UNIVERSAL_P="1"
	     AC_DEFINE([BUILD_UNIVERSAL_BINARY], 1,
		       [Define if we are building an OS X Universal Binary.])
	     AC_MSG_RESULT(yes)
           ;;
           * ) AC_MSG_ERROR([--enable-universal-binary only works on Mac OS X])
           ;;
         esac
           ],
   	[dnl
	 S48_BUILD_UNIVERSAL_P="0"
	 AC_MSG_RESULT(no)])])
dnl
dnl
dnl
define(S48_PICK_GC, [dnl
AC_ARG_ENABLE([gc],
[AC_HELP_STRING([--enable-gc=GC],
                [choose garbage collector (twospace, bibop), default is twospace])],
              [dnl
                case $enableval in
                  twospace )
			AC_DEFINE([S48_GC_TWOSPACE], 1, [Define if building with two-space GC.])
			GC_OBJS='${GC_TWOSPACE_OBJS}' ;;
                  bibop )
			AC_DEFINE([S48_GC_BIBOP], 1, [Define if building with BIBOP GC.])
			GC_OBJS='${GC_BIBOP_OBJS}' ;;
                  * ) AC_MSG_ERROR([Invalid argument to --enable-gc]) ;;
		esac
	      ],
	      [AC_DEFINE([S48_GC_TWOSPACE], 1, [Define if building with two-space GC.])
	       GC_OBJS='${GC_TWOSPACE_OBJS}'])dnl
])dnl
])
dnl
dnl We might want AC_WORDS_BIGENDIAN in the future.
dnl We might want AC_CHAR_UNSIGNED in the future.
dnl
define(S48_POSIX_LIBC, [dnl
echo checking for RISC/OS POSIX library lossage
if test -f /usr/posix/usr/lib/libc.a; then
  LIBS="${LIBS} /usr/posix/usr/lib/libc.a"
fi
])dnl
dnl
dnl
dnl Determine the name of compiler option for generating position
dnl independent code.
define(S48_PIC_OPTION_NAME, [dnl
	AC_MSG_CHECKING([how to compile position independent code])
	case "$host_os" in
		solaris* )
		   if test "$GCC" = "yes"; then
			PIC="-fPIC"
		   else
			# for SUN's compiler
			PIC="-KPIC"
		   fi
		;;
		darwin*|macosx* )
		   # Code on this platform is PIC by default
		   PIC=""
		;;
		*)
 	           PIC="-fPIC"
		;;
	esac
	if test "$PIC" = ""; then
	   AC_MSG_RESULT(no extra option necessary)
  	else
	   AC_MSG_RESULT($PIC)
	fi
])dnl
dnl
dnl
dnl
dnl -rdynamic is needed for loading external code
define(S48_LDFLAGS, [dnl
	AC_MSG_CHECKING([-rdynamic])
	oldLDFLAGS="$LDFLAGS"
	LDFLAGS="$LDFLAGS -rdynamic"
	AC_TRY_RUN([int main() { return 0;}],
		[AC_MSG_RESULT(yes)],
		[AC_MSG_RESULT(no)
			LDFLAGS="$oldLDFLAGS"],
		[AC_MSG_RESULT(no)
			LDFLAGS="$oldLDFLAGS"])
	AC_MSG_CHECKING([LDFLAGS_VM])
	case "$host_os" in
		aix* )
 			if test "$GCC" = "yes"; then
				LDFLAGS_VM="-Xlinker -brtl -Xlinker -bE:$srcdir/c/scheme48.exp"
			else
				LDFLAGS_VM="-brtl -bE:$srcdir/c/scheme48.exp"
			fi
		;;
		* )
			LDFLAGS_VM=
		;;
	esac
 	AC_MSG_RESULT([$LDFLAGS_VM])
])dnl
dnl
define(S48_INLINE, [dnl
AC_MSG_CHECKING([for inline keyword])
AC_COMPILE_IFELSE([#include <stdio.h>

inline void f(void)
{
  printf("inlined");
}], [AC_MSG_RESULT([yes])
     AC_DEFINE([HAVE_INLINE], [1], [Define if the C compiler supports the inline keyword])],
    [AC_MSG_RESULT([no])])
])
dnl
define(S48_IEEE_ENDIANNESS, [dnl
build_universal="$1"
AC_MSG_CHECKING([IEEE floating-point endianness])
if test "$build_universal" = "1";
then 
  AC_MSG_RESULT([building Universal Binary; using compiler defined macros instead])
else
AC_TRY_RUN([#include <stdio.h>
#include <inttypes.h>

typedef uint32_t word32_t;

typedef union { double d; word32_t word[2]; } double_overlay;

#define DOUBLE_WORD0(x) ((double_overlay*)&(x))->word[0]
#define DOUBLE_WORD1(x) ((double_overlay*)&(x))->word[1]


int
main(void)
{
  double n = 0.3;
	
  /* least significant byte first */
  if ((DOUBLE_WORD0(n) == 0x33333333) && (DOUBLE_WORD1(n) == 0x3fd33333))
    return 0;
  /* most significant byte first */
  else if ((DOUBLE_WORD1(n) == 0x33333333) && (DOUBLE_WORD0(n) == 0x3fd33333))
    return 1;
  else {
    fprintf(stderr, "WARNING: unknown IEEE format; assuming IEEE with least significant byte first\n");
    return 0;
  }
}], ieee_endianness="least first", ieee_endianness="most first", ieee_endianness="least first")
AC_MSG_RESULT([$ieee_endianness])
if test "$ieee_endianness" = "most first"; then
  AC_DEFINE([IEEE_MOST_FIRST], 1, [Define if IEEE doubles are stored with most-significant byte first.])
fi
fi
])dnl
dnl
define(S48_CREATE_BUILD_DIRS, [dnl
        mkdir -p c/bibop
        mkdir -p c/unix
        mkdir -p c/posix
        mkdir -p c/fake
])dnl
dnl
dnl
dnl
define(S48_DYNAMIC_EXTERNALS, [dnl
	dnl
	AC_CHECK_PROGS([LD], [ld cc gcc])
	AC_MSG_CHECKING([compile and link flags for dynamic externals])
	DYNAMIC_EXTERNALS_LDFLAGS_IN_PLACE=""
	case "$host_os" in
		hpux* )
			dnl +z means position-independent code
			DYNAMIC_EXTERNALS_CFLAGS='+z -D_HPUX_SOURCE'
			DYNAMIC_EXTERNALS_LDFLAGS='-b'
		;;
		aix* )
			DYNAMIC_EXTERNALS_CFLAGS=''
			dnl -bM:SRE means shared object
			dnl -brtl means run-time linking is enabled
			dnl -bnoentry means no default entry point
			DYNAMIC_EXTERNALS_LDFLAGS='-bM:SRE -brtl -bI:\$(incdir)/scheme48.exp -bnoentry -bE:\$(incdir)/scheme48-external.exp -lc'
			DYNAMIC_EXTERNALS_LDFLAGS_IN_PLACE='-bM:SRE -brtl -bI:\$(srcdir)/c/scheme48.exp -bnoentry -bE:\$(srcdir)/c/scheme48-external.exp -lc'
		;;
		darwin*|macosx* )
			DYNAMIC_EXTERNALS_CFLAGS='-fno-common'
			DYNAMIC_EXTERNALS_LDFLAGS="$CFLAGS $LDFLAGS -bundle -flat_namespace -undefined suppress"
			dnl linker workaround for MacOSX
			LD="$CC"
		;;
		solaris* )
			DYNAMIC_EXTERNALS_CFLAGS="$PIC"
			dnl -G means shared object
			DYNAMIC_EXTERNALS_LDFLAGS="$LDFLAGS -G"
			LD="$CC"
		;;
		linux* )
			DYNAMIC_EXTERNALS_CFLAGS="$PIC"
			if test "$LD" = "ld"; then
				DYNAMIC_EXTERNALS_LDFLAGS="-shared $LD_LDFLAGS"
			else
				DYNAMIC_EXTERNALS_LDFLAGS="-shared $GCC_LDFLAGS"
			fi
		;;
		cygwin* )
			LD="$CC"
			DYNAMIC_EXTERNALS_CFLAGS=""
			DYNAMIC_EXTERNALS_LDFLAGS='-shared $(bindir)/scheme48vm.a'
			DYNAMIC_EXTERNALS_LDFLAGS_IN_PLACE='-shared $(srcdir)/scheme48vm.a'
		;;
		* )
			DYNAMIC_EXTERNALS_CFLAGS="$PIC"
			DYNAMIC_EXTERNALS_LDFLAGS='-shared'
		;;
	esac
	if test -z "$DYNAMIC_EXTERNALS_LDFLAGS_IN_PLACE"; then
		DYNAMIC_EXTERNALS_LDFLAGS_IN_PLACE="$DYNAMIC_EXTERNALS_LDFLAGS"
	fi
	AC_MSG_RESULT([$DYNAMIC_EXTERNALS_CFLAGS, $DYNAMIC_EXTERNALS_LDFLAGS])
])dnl
dnl
AC_DEFUN([S48_PTHREAD_TRY_FLAGS], [
	if test "$pthreads_done" = "no"; then
	  flags_result=""

	  oldCFLAGS="$CFLAGS"
	  CFLAGS="$CFLAGS $1"
	  AC_TRY_RUN([#include <pthread.h>
int
main(void)
{
  pthread_kill(pthread_self(), 0);
}],
	    [flags_result="$1 (compile)"],
	    [CFLAGS="$oldCFLAGS"])

	  oldLDFLAGS="$LDFLAGS"
	  LDFLAGS="$LDFLAGS $1"
	  AC_TRY_RUN([#include <pthread.h>
int
main(void)
{
  pthread_kill(pthread_self(), 0);
}],
		  [flags_result="$flags_result $1 (link)"
		   pthreads_done="yes"],
		  [LDFLAGS="$oldLDFLAGS"])
	if test -n "$flags_result"; then
		AC_MSG_RESULT($flags_result)
	fi
      fi
])
dnl
dnl
dnl must run after S48_DYNAMIC_EXTERNALS
define(S48_PTHREADS, [dnl
       AC_CHECK_HEADERS([pthread.h],[dnl
         pthreads_done="no"
         AC_MSG_CHECKING([Pthreads support])
	 S48_PTHREAD_TRY_FLAGS([-mt])
	 S48_PTHREAD_TRY_FLAGS([-pthread])
	 S48_PTHREAD_TRY_FLAGS([-pthreads])
	 S48_PTHREAD_TRY_FLAGS([-mthreads])
	 S48_PTHREAD_TRY_FLAGS([-thread])
 	])
       ])
dnl
dnl
dnl must run after S48_DYNAMIC_EXTERNALS
define(S48_MISALIGNED_DOUBLES, [dnl
	if test "$GCC" = "yes"; then
		AC_MSG_CHECKING([-munaligned-doubles])
		oldCFLAGS="$CFLAGS"
		CFLAGS="$CFLAGS -munaligned-doubles"
		AC_TRY_RUN([int main() { return 0;}],
			[AC_MSG_RESULT(yes)
				DYNAMIC_EXTERNALS_CFLAGS="$DYNAMIC_EXTERNALS_CFLAGS -munaligned-doubles"],
			[AC_MSG_RESULT(no)
				CFLAGS="$oldCFLAGS"],
			[AC_MSG_RESULT(no)
				CFLAGS="$oldCFLAGS"])
	fi
])dnl
dnl
dnl
dnl
AC_INIT(c/prescheme.h)
     AC_CONFIG_HEADER(c/sysdep.h)
     AC_CONFIG_HEADER(c/scheme48arch.h)
     AC_CANONICAL_HOST
     dnl set the cross-compile flag before we try anything.
     AC_TRY_RUN([int main() { return 0;}], [], [], [true])
     S48_CC
     S48_PICK_GC
     S48_ENABLE_FORCE_32BIT
     S48_DETERMINE_BITS_PER_BYTE
     S48_DETERMINE_POINTER_SIZE
     S48_DETERMINE_BIT_SUFFIX
     S48_ENABLE_UNIVERSAL_BINARY
     S48_OSX_ARCH_FLAGS($S48_BUILD_UNIVERSAL_P,$S48_FORCE_32_P)
     S48_PIC_OPTION_NAME
     S48_CREATE_BUILD_DIRS
     S48_LDFLAGS
     AC_ISC_POSIX
     S48_INLINE
     AC_PROG_INSTALL
     AC_CHECK_LIB(m, main)
     AC_CHECK_LIB(dl, main)
     AC_CHECK_LIB(mld, main)
     AC_CHECK_LIB(nsl, main)
     AC_CHECK_LIB(gen, main)
     AC_CHECK_LIB(socket, main)
     AC_CHECK_LIB(sun, getpwnam)
     S48_POSIX_LIBC
     AC_CONST
     AC_MSG_CHECKING(for socklen_t)
     AC_TRY_COMPILE([#include <sys/types.h>
                     #include <sys/socket.h>
                     socklen_t x;
                    ],[],
		    [AC_MSG_RESULT(yes)],
		    [AC_TRY_COMPILE([#include <sys/types.h>
                                     #include <sys/socket.h>
                                     int accept (int,
				                 struct sockaddr *,
						 size_t *);
                                    ],[],
		                    [AC_MSG_RESULT(size_t)
                                     AC_DEFINE(socklen_t,size_t)],
				    [AC_MSG_RESULT(int)
                                     AC_DEFINE(socklen_t,int)])])
     AC_RETSIGTYPE
     AC_TYPE_UINTPTR_T
     AC_TYPE_UINT16_T
     AC_CHECK_HEADERS(libgen.h sys/timeb.h posix/time.h)
     AC_CHECK_HEADERS(sys/select.h)
     AC_CHECK_HEADERS(sysexits.h)
     AC_CHECK_HEADERS(langinfo.h)
     AC_CHECK_FUNC(nl_langinfo, [], [AC_LIBOBJ([c/fake/langinfo])])
     AC_CHECK_FUNCS(gettimeofday ftime select setitimer sigaction)
     AC_CHECK_HEADERS(poll.h)
     AC_CHECK_FUNCS(poll)
     AC_CHECK_FUNC(dlopen, [AC_DEFINE(HAVE_DLOPEN, 
				1, [Define to 1 if the interface to the dynamic linker exists])])
     AC_CHECK_FUNCS(socket chroot)
     AC_CHECK_FUNC(strerror, AC_DEFINE(HAVE_STRERROR),
			      [AC_LIBOBJ([c/fake/strerror.o])])
dnl Some idiot renamed `environ' as `__environ' in some versions of Linux.
dnl POSIX says it's `environ'.
     AC_MSG_CHECKING([environ])
     AC_TRY_LINK([],
		 [extern char **environ;
		  if (environ)
		     return 0;
		  else
		     return 1;],
               dnl Have `environ'
		 [AC_DEFINE(ENVIRON_NAME,environ)
		  AC_MSG_RESULT([using environ])],
               dnl Do not have `environ'
	         [AC_TRY_LINK([],
		              [extern char **__environ;
			       if (__environ)
			         return 0;   
			       else
				 return 1;],
                            dnl Have `__environ'
		               [AC_DEFINE(ENVIRON_NAME,__environ)
	     		        AC_MSG_RESULT([using __environ])],
                           dnl Do not have `__environ'
                               [AC_MSG_WARN([no environ variable found])
                                AC_LIBOBJ([c/fake/environ.o])])])
     AC_MSG_CHECKING([__NEXT__])
     AC_TRY_LINK(,[
#ifdef	__NeXT__
return 0;
#else
fail
#endif
],
		CC="$CC -posix"
		AC_DEFINE(HAVE_SIGACTION)
		AC_MSG_RESULT([yes]),
		AC_MSG_RESULT([no]))
     S48_IEEE_ENDIANNESS($S48_BUILD_UNIVERSAL_P)
     S48_DYNAMIC_EXTERNALS
     S48_PTHREADS
     S48_MISALIGNED_DOUBLES
     AC_SUBST(CFLAGS)
     AC_SUBST(LDFLAGS)
     AC_SUBST(LD)
     AC_SUBST(LDFLAGS_VM)
     AC_SUBST(DYNAMIC_EXTERNALS_CFLAGS)
     AC_SUBST(DYNAMIC_EXTERNALS_LDFLAGS)
     AC_SUBST(DYNAMIC_EXTERNALS_LDFLAGS_IN_PLACE)
     AC_SUBST(GC_OBJS)
     AC_SUBST(S48_GC_TWOSPACE)
     AC_SUBST(S48_GC_BIBOP)
     AC_SUBST(BIT_SUFFIX)
AC_OUTPUT(Makefile)
